using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace AntEater.ComponentModel.BuildElements
{
    /// <summary>
    /// Provides collection of task parameters.
    /// </summary>
    [Serializable()]
    public class TaskParameterCollection:KeyedCollection<string,TaskParameter>,ICloneable
    {
        /// <summary>
        /// Occurs when the content of the collection changed
        /// </summary>
        public event EventHandler<CollectionChangeEventArgs> CollectionChanged;

        /// <summary>
        /// Adds the range.
        /// </summary>
        /// <param name="collection">The collection.</param>
        public void AddRange(IEnumerable<TaskParameter> collection) {
            if (collection == null) { throw new ArgumentNullException("collection"); }

            foreach (TaskParameter item in collection) {
                base.Add(item);
            }
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone() {
            TaskParameterCollection newCollection = new TaskParameterCollection();

            foreach (TaskParameter parameter in this) {
                newCollection.Add(parameter.Clone() as TaskParameter);
            }

            return newCollection;
        }

        /// <summary>
        /// Inserts an element into the <see cref="T:System.Collections.ObjectModel.KeyedCollection`2"></see> at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which item should be inserted.</param>
        /// <param name="item">The object to insert.</param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index is less than 0.-or-index is greater than <see cref="P:System.Collections.ObjectModel.Collection`1.Count"></see>.</exception>
        protected override void InsertItem(int index, TaskParameter item) {
            base.InsertItem(index, item);
            item.PropertyChanged += new PropertyChangedEventHandler(ItemPropertyChanged);
            OnCollectionChanged(CollectionChangeAction.Add);
        }

        /// <summary>
        /// Replaces the item at the specified index with the specified item.
        /// </summary>
        /// <param name="index">The zero-based index of the item to be replaced.</param>
        /// <param name="item">The new item.</param>
        protected override void SetItem(int index, TaskParameter item) {
            this[index].PropertyChanged -= new PropertyChangedEventHandler(ItemPropertyChanged);
            base.SetItem(index, item);
            item.PropertyChanged += new PropertyChangedEventHandler(ItemPropertyChanged);
            OnCollectionChanged(CollectionChangeAction.Refresh);
        }

        /// <summary>
        /// Removes the element at the specified index of the <see cref="T:System.Collections.ObjectModel.KeyedCollection`2"></see>.
        /// </summary>
        /// <param name="index">The index of the element to remove.</param>
        protected override void RemoveItem(int index) {
            this[index].PropertyChanged -= new PropertyChangedEventHandler(ItemPropertyChanged);
            base.RemoveItem(index);
            OnCollectionChanged(CollectionChangeAction.Remove);
        }

        /// <summary>
        /// Removes all elements from the <see cref="T:System.Collections.ObjectModel.KeyedCollection`2"></see>.
        /// </summary>
        protected override void ClearItems() {
            foreach (TaskParameter item in this) {
                item.PropertyChanged -= new PropertyChangedEventHandler(ItemPropertyChanged);
            }
            base.ClearItems();
            OnCollectionChanged(CollectionChangeAction.Refresh);
        }

        /// <summary>
        /// Extracts the key from the specified element.
        /// </summary>
        /// <param name="item">The element from which to extract the key.</param>
        /// <returns>The key for the specified element.</returns>
        protected override string GetKeyForItem(TaskParameter item) {
            return item.Name;
        }

        /// <summary>
        /// Called when [collection changed].
        /// </summary>
        /// <param name="action">The action.</param>
        protected void OnCollectionChanged(CollectionChangeAction action) {
            if (CollectionChanged != null) {
                CollectionChanged(this, new CollectionChangeEventArgs(action, this));
            }
        }

        /// <summary>
        /// Handles PropertyChanged Event of all Items.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) {
            OnCollectionChanged(CollectionChangeAction.Refresh);
        }
    }
}
